package com.ccplay.dataservice.web;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.oxygen.constants.Constant;
import com.oxygen.enums.ApiMethodEnum;
import com.oxygen.enums.ApiMsgEnum;
import com.oxygen.util.HttpClientUtil;
import com.oxygen.util.HttpRequestExceptionListener;
import com.oxygen.util.JsonUtil;
import com.oxygen.util.StringUtil;
import com.oxygen.web.SuperDispatcherServlet;
import com.oxygen.web.WebHelper;

/**
 * API总控制中心
 * 
 * @author Daniel
 */
@Controller
public class ApiCenterAction extends BaseAction {

	@RequestMapping(value = { "/apicenter", "/apicenter/" })
	public String apiCenter(@RequestBody String bodyData, HttpServletRequest req, HttpServletResponse rsp) {
		String data = req.getParameter(Constant.DATA);
		if (StringUtil.isEmpty(data)) {
			data = bodyData;
		}
		if (StringUtils.isEmpty(data)) {
			return this.outputApiFinalResponse(null, ApiMsgEnum.MissParameterException, rsp);
		}
		JsonElement dataJsonEle = JsonUtil.jsonToObject(data, JsonElement.class);
		if (dataJsonEle == null || dataJsonEle.isJsonNull() || dataJsonEle.isJsonPrimitive() || dataJsonEle.isJsonArray()) {
			return this.outputApiFinalResponse(null, ApiMsgEnum.BadRequestException, rsp);
		}
		String retJson = this.doService(dataJsonEle.getAsJsonObject(), req);
		return WebHelper.outputJson(retJson, rsp);
	}

	@RequestMapping(value = { "/apicenter/{codes}/{key}" })
	public String apiCenter(@RequestBody String bodyData, @PathVariable String codes, @PathVariable String key, HttpServletRequest req, HttpServletResponse rsp) {
		String data = req.getParameter(Constant.DATA);
		if (StringUtil.isEmpty(data)) {
			data = bodyData;
		}
		if (StringUtils.isEmpty(data)) {
			return this.outputApiFinalResponse(null, ApiMsgEnum.MissParameterException, rsp);
		}
		JsonElement dataJsonEle = JsonUtil.jsonToObject(data, JsonElement.class);
		if (dataJsonEle == null || dataJsonEle.isJsonNull() || dataJsonEle.isJsonPrimitive() || dataJsonEle.isJsonArray()) {
			return this.outputApiFinalResponse(null, ApiMsgEnum.ForbiddenException, rsp);
		}
		String retJson = this.doService(dataJsonEle.getAsJsonObject(), req);
		// this.saveNginxCacheInfo(req, codes, key, retJson);
		return WebHelper.outputJson(retJson, rsp);
	}

	private String doService(JsonObject functionCodeJsonObj, HttpServletRequest req) {
		String requestIp = WebHelper.getRequestIp(req);
		String agent = WebHelper.extractRequestHeader(req, "User-Agent");
		JsonObject clientEventObj = this.extractClientEventFromHeader(req);
		StringBuffer buf = new StringBuffer("{");
		Set<Map.Entry<String, JsonElement>> functionCodeSet = functionCodeJsonObj.entrySet();
		int i = 0;
		for (Entry<String, JsonElement> functionCodeEntry : functionCodeSet) {
			String functionCode = functionCodeEntry.getKey();
			JsonElement paramJsonEle = functionCodeEntry.getValue();
			if (!StringUtils.isEmpty(functionCode) && paramJsonEle != null && paramJsonEle.isJsonObject()) {
				// 根据functionCode来确定在哪一个体系的服务器上
				ApiMethodEnum aEnum = ApiMethodEnum.getApiMethodEnum(functionCode);
				if (aEnum != null) {
					// 调用API
					JsonObject paramJsonObj = paramJsonEle.getAsJsonObject();
					paramJsonObj.addProperty(Constant.REQUEST_IP, requestIp);
					paramJsonObj.addProperty(Constant.USER_AGENT, agent);
					if (clientEventObj != null) {
						paramJsonObj.addProperty(Constant.DEVICE_NO, (clientEventObj.get("imei") == null || clientEventObj.get("imei").isJsonNull()) ? "" : clientEventObj.get("imei").getAsString());
						paramJsonObj.addProperty(Constant.MODEL_NAME,(clientEventObj.get("model_name") == null || clientEventObj.get("model_name").isJsonNull()) ? "" : clientEventObj.get("model_name").getAsString());
					    paramJsonObj.addProperty(Constant.TRACK_OBJECT,(clientEventObj.get("track_object") == null || clientEventObj.get("track_object").isJsonNull()) ? "" : clientEventObj.get("track_object").getAsString());
						paramJsonObj.addProperty(Constant.VERSION_CODE, (clientEventObj.get("versionCode") == null || clientEventObj.get("versionCode").isJsonNull()) ? "" : clientEventObj.get("versionCode").getAsString());

					}
					String retJson = this.callApi(aEnum, paramJsonObj);
					if (retJson != null) {
						retJson = retJson.substring(1, retJson.length() - 1);
					}
					buf.append(retJson);
					if (i != functionCodeSet.size() - 1) {
						buf.append(",");
					}
				}
			}
			i++;
		}
		buf.append("}");
		return buf.toString();
	}

	/**
	 * 调用API
	 * 
	 * @param ApiMethodEnum
	 *            API FUNCTION CODE
	 * @param jsonEle
	 *            json对象
	 * @return
	 * @author Daniel
	 */
	private String callApi(final ApiMethodEnum apiMethodEnum, JsonObject jsonObj) {
		if (jsonObj != null && !jsonObj.isJsonNull()) {
			if (!jsonObj.has(Constant.API_KEY) || jsonObj.get(Constant.API_KEY) == null || jsonObj.get(Constant.API_KEY).isJsonNull() || "".equals(jsonObj.get(Constant.API_KEY).getAsString())) {
				jsonObj.addProperty(Constant.API_KEY, defaultApiKey);
			}
			if (!jsonObj.has(Constant.ACCESS_TOKEN) || jsonObj.get(Constant.ACCESS_TOKEN) == null || jsonObj.get(Constant.ACCESS_TOKEN).isJsonNull()
					|| "".equals(jsonObj.get(Constant.ACCESS_TOKEN).getAsString())) {
				jsonObj.addProperty(Constant.ACCESS_TOKEN, Constant.DEFAULT_ACCESS_TOKEN);
			}
		}
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put(apiMethodEnum.getCode(), jsonObj);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		final String dataJson = JsonUtil.objectToJson(dataMap, Map.class);
		paramMap.put(Constant.DATA, dataJson);
		HttpClientUtil clientUtil = new HttpClientUtil();
		Map<String, String> head = new HashMap<String, String>();
		int port = SuperDispatcherServlet.getlocalPort();
		head.put("referer", "dataservice/" + port);
		head.put("X-Hash-ip", jsonObj.get(Constant.REQUEST_IP).getAsString());
		clientUtil.setHttpSetting(head);
		clientUtil.setTimeOut(20000);
		// 服务器应用异常预警通知
		clientUtil.setExceptionListener(new HttpRequestExceptionListener() {
			@Override
			public void exceptionData(final Map<String, String> data) {
				String httpCode = data.get("code");
				final String exception = data.get("exception");
				if (!"200".equals(httpCode)) {
					myExecutor.execute(new Runnable() {
						@Override
						public void run() {
							String alterContent = "out invoke error: service[" + apiMethodEnum.getApiServer() + "] --- functionCode[" + apiMethodEnum.getCode() + "] --- msg[" + exception + "]";
							loger.info("out invoke error:" + alterContent);
							// TODO:预警通知
						}
					});
				}
			}
		});
		String retJson = clientUtil.doHttpPost(this.getApiServeUrl(apiMethodEnum.getApiServer()), paramMap);
		return retJson;
	}

}
